package com.xu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.xu.base.enums.ResponseCodeEnum;
import com.xu.base.model.BaseSelectVo;
import com.xu.base.utils.AssertUtils;
import com.xu.mybatis.model.PageInfo;
import com.xu.security.utils.SecurityUtils;
import com.xu.system.model.convert.DictConvert;
import com.xu.system.model.entity.SysDict;
import com.xu.system.model.entity.SysDictItem;
import com.xu.system.model.pojo.dict.*;
import com.xu.system.service.IDictService;
import com.xu.system.service.db.ISysDictItemService;
import com.xu.system.service.db.ISysDictService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: 许乾伟
 * @Date: 2024/12/17 17:06
 */
@Service
public class DictServiceImpl implements IDictService {

    @Resource
    ISysDictService sysDictService;
    @Resource
    ISysDictItemService sysDictItemService;
    @Resource
    DictConvert dictConvert;
    @Override
    public Boolean addDict(AddDictReq req) {
        verifyDictName(req.getDictName(),null);
        SysDict sysDict = dictConvert.toSysDict(req);
        return sysDictService.save(sysDict);
    }

    @Override
    public Boolean editDict(EditDictReq req) {
        verifyDictName(req.getDictName(),req.getDictId());
        SysDict sysDict = sysDictService.getById(req.getDictId());
        AssertUtils.isNull(sysDict,ResponseCodeEnum.DATA_FAILED,"未查询到字典，无法编辑");
        verifyDictName(req.getDictName(), sysDict.getId());
        sysDict.setDictName(req.getDictName())
                .setRemark(req.getRemark())
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysDictService.updateById(sysDict);
    }

    @Override
    public Boolean delDict(Long dictId) {
        SysDict sysDict = sysDictService.getById(dictId);
        AssertUtils.isNull(sysDict, ResponseCodeEnum.DATA_FAILED, "未查询到字典，无法删除");
        sysDict.setIsDelete(Boolean.TRUE)
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysDictService.updateById(sysDict);
    }

    @Override
    public DictVo detailDict(Long dictId) {
        SysDict sysDict = sysDictService.getById(dictId);
        AssertUtils.isNull(sysDict, ResponseCodeEnum.DATA_FAILED, "未查询到字典");
        return dictConvert.toDictVo(sysDict);
    }

    @Override
    public PageInfo<DictVo> queryPageDict(QueryDictReq req) {
        PageHelper.startPage(req.getPageNum(),req.getPageSize());
        List<SysDict> list = searchDictList(req);
        PageInfo<SysDict> pageData = new PageInfo<>(list);
        PageInfo<DictVo> pageResult = dictConvert.toDictVoPage(pageData);
        return pageResult;
    }

    @Override
    public Boolean addDictItem(AddDictItemReq req) {
        verifyDictLabel(req.getDictLabel(),req.getDictId(),null);
        verifyDictValue(req.getDictValue(),req.getDictId(),null);
        SysDict dict = sysDictService.getById(req.getDictId());
        AssertUtils.isNull(dict, ResponseCodeEnum.DATA_FAILED, "未查询到字典，无法添加字典项");
        verifyDictLabel(req.getDictLabel(),req.getDictId(),null);
        verifyDictValue(req.getDictValue(),req.getDictId(),null);
        SysDictItem sysDictItem = dictConvert.toSysDictItem(req);
        sysDictItem.setDictCode(dict.getDictCode());
        return sysDictItemService.save(sysDictItem);
    }

    @Override
    public Boolean editDictItem(EditDictItemReq req) {
        verifyDictLabel(req.getDictLabel(),req.getDictId(),req.getId());
        verifyDictValue(req.getDictValue(),req.getDictId(),req.getId());
        SysDictItem sysDictItem = sysDictItemService.getById(req.getId());
        AssertUtils.isNull(sysDictItem, ResponseCodeEnum.DATA_FAILED,"未查询到字典项，无法编辑");
        verifyDictLabel(req.getDictLabel(),req.getDictId(),req.getId());
        verifyDictValue(req.getDictValue(),req.getDictId(),req.getId());
        sysDictItem.setDictLabel(req.getDictLabel())
                .setDictValue(req.getDictValue())
                .setRemark(req.getRemark())
                .setSort(req.getSort())
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysDictItemService.updateById(sysDictItem);
    }

    @Override
    public Boolean delDictItem(Long dictItemId) {
        SysDictItem sysDictItem = sysDictItemService.getById(dictItemId);
        AssertUtils.isNull(sysDictItem, ResponseCodeEnum.DATA_FAILED, "未查询到字典项，无法编辑");
        sysDictItem.setIsDelete(Boolean.TRUE)
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysDictItemService.updateById(sysDictItem);
    }

    @Override
    public DictItemVo detailDictItem(Long dictItemId) {
        SysDictItem sysDictItem = sysDictItemService.getById(dictItemId);
        AssertUtils.isNull(sysDictItem, ResponseCodeEnum.DATA_FAILED, "未查询到字典项");
        return dictConvert.toDictItemVo(sysDictItem);
    }

    @Override
    public PageInfo<DictItemVo> queryPageDictItem(QueryDictItemReq req) {
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        List<SysDictItem> list = searchDictItemList(req);
        PageInfo<SysDictItem> pageData = new PageInfo<>(list);
        PageInfo<DictItemVo> pageResult = dictConvert.toDictItemVoPage(pageData);
        return pageResult;
    }

    @Override
    public Map<String, String> queryDictMap(String dictCode) {
        List<SysDictItem> list = sysDictItemService.list(new QueryWrapper<SysDictItem>()
                .eq(SysDictItem.DICT_CODE,dictCode)
                .eq(SysDictItem.IS_DELETE,Boolean.FALSE)
                .orderByAsc(SysDictItem.SORT));
        if (list.isEmpty()){
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.toMap(SysDictItem::getDictValue, SysDictItem::getDictLabel));
    }


    @Override
    public List<BaseSelectVo<String, String>> selectListByDictCode(String dictCode) {
        List<SysDictItem> list = sysDictItemService.list(new QueryWrapper<SysDictItem>()
                .eq(SysDictItem.DICT_CODE,dictCode)
                .eq(SysDictItem.IS_DELETE,Boolean.FALSE)
                .orderByAsc(SysDictItem.SORT));
        if (list.isEmpty()){
            return new ArrayList<>();
        }
        List<BaseSelectVo<String, String>> result = new ArrayList<>();
        for (SysDictItem sysDictItem : list) {
            BaseSelectVo<String, String> vo = new BaseSelectVo<>();
            vo.setKey(sysDictItem.getDictValue());
            vo.setValue(sysDictItem.getDictLabel());
            result.add(vo);
        }
        return result;
    }

    /**
     * 查询字典项列表
     * @param req
     * @return
     */
    public List<SysDictItem> searchDictItemList(QueryDictItemReq req){
        List<SysDictItem> list = sysDictItemService.list(new QueryWrapper<SysDictItem>()
                .eq(SysDictItem.DICT_ID, req.getDictId())
                .eq(SysDictItem.IS_DELETE, Boolean.FALSE)
                .eq(StringUtils.hasText(req.getDictLabel()), SysDictItem.DICT_LABEL, req.getDictLabel())
                .eq(req.getStatus() != null, SysDictItem.STATUS, req.getStatus())
                .orderByAsc(SysDictItem.SORT));
        return list;
    }
    /**
     * 字典查询
     * @param req
     * @return
     */
    public List<SysDict> searchDictList(QueryDictReq req){
        List<SysDict> list = sysDictService.list(new QueryWrapper<SysDict>()
                .like(StringUtils.hasText(req.getDictName()),SysDict.DICT_NAME,req.getDictName())
                .like(StringUtils.hasText(req.getDictCode()),SysDict.DICT_CODE,req.getDictCode())
                .ge(StringUtils.hasText(req.getStartTime()), SysDict.UPDATE_TIME, req.getStartTime())
                .le(StringUtils.hasText(req.getEndTime()), SysDict.UPDATE_TIME, req.getEndTime())
                .eq(SysDict.IS_DELETE,Boolean.FALSE)
                .orderByDesc(SysDict.UPDATE_TIME));
        return list;
    }
    /**
     * 校验字典名称是否唯一
     * @param dictName
     * @param id
     */
    private void verifyDictName(String dictName, Long id) {
        long count = sysDictService.count( new QueryWrapper<SysDict>()
                .ne(id != null, SysDict.ID, id)
                .eq(SysDict.DICT_NAME, dictName.trim())
                .eq(SysDict.IS_DELETE, Boolean.FALSE));
        AssertUtils.isTrue(count > 0, ResponseCodeEnum.DATA_FAILED, "字典名称已存在,请检查!");
    }

    /**
     * 校验字典标签是否唯一
     * @param dictLabel 字典项标签
     * @param dictId 字典id
     * @param id 字典项id
     */
    private void verifyDictLabel(String dictLabel,Long dictId, Long id) {
        long count = sysDictItemService.count(new QueryWrapper<SysDictItem>()
                .ne(id != null, SysDictItem.ID, id)
                .eq(SysDictItem.DICT_ID, dictId)
                .eq(SysDictItem.DICT_LABEL, dictLabel)
                .eq(SysDictItem.IS_DELETE, Boolean.FALSE));
        AssertUtils.isTrue(count > 0, ResponseCodeEnum.DATA_FAILED, "字典项标签已存在,请检查!");
    }
    /**
     * 校验字典值是否唯一
     * @param dictValue 字典项值
     * @param dictId 字典id
     * @param id 字典项id
     */
    private void verifyDictValue(String dictValue,Long dictId, Long id) {
        long count = sysDictItemService.count(new QueryWrapper<SysDictItem>()
                .ne(id != null, SysDictItem.ID, id)
                .eq(SysDictItem.DICT_ID, dictId)
                .eq(SysDictItem.DICT_VALUE, dictValue)
                .eq(SysDictItem.IS_DELETE, Boolean.FALSE));
        AssertUtils.isTrue(count > 0, ResponseCodeEnum.DATA_FAILED, "字典项值已存在,请检查!");
    }
}
